home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSNARP.C < prev    next >
C/C++ Source or Header  |  1991-10-24  |  12KB  |  455 lines

  1. /* File MSNARP.C
  2.  * ARP and RARP packet processor
  3.  *
  4.  * Copyright (C) 1991, University of Waterloo.
  5.  * Copyright (C) 1991, Trustees of Columbia University in the
  6.  *  City of New York.  Permission is granted to any individual or
  7.  *  institution to use, copy, or redistribute this software as long as
  8.  *  it is not sold for profit and this copyright notice is retained.
  9.  *
  10.  * Original version created by Erick Engelke of the University of
  11.  *  Waterloo, Waterloo, Ontario, Canada.
  12.  * Adapted and modified for MS-DOS Kermit by Joe R. Doupnik, 
  13.  *  Utah State University, jrd@cc.usu.edu, jrd@usu.Bitnet.
  14.  *
  15.  * Last edit
  16.  * 6 Sept 1991
  17.  *
  18.  * Address Resolution Protocol
  19.  *
  20.  *  Externals:
  21.  *  ap_handler(pb) - returns 1 on handled correctly, 0 on problems
  22.  *  arp_resolve - rets 1 on success, 0 on fail
  23.  *               - does not return hardware address if passed NULL for buffer
  24.  *
  25.  */
  26. #include "msntcp.h"
  27. #include "msnlib.h"
  28.  
  29. #ifdef KERMIT
  30. #define MAX_ARP_DATA 10
  31. #else
  32. #define MAX_ARP_DATA 40
  33. #define NEW_EXPIRY
  34. #endif    /* KERMIT */
  35.  
  36. #define MAX_ARP_ALIVE  300        /* five minutes */
  37. #define MAX_ARP_GRACE  100        /* additional grace upon expiration */
  38.  
  39. eth_address eth_none = { 0,0,0 };
  40.  
  41. typedef struct
  42.     {
  43.     longword    ip;
  44.     eth_address    hardware;
  45.     byte        flags;
  46.     byte        bits;        /* bits in network */
  47.     longword    expiry;
  48.     } arp_tables;
  49.  
  50. typedef struct
  51.     {
  52.     longword    gate_ip;
  53.     longword    subnet;
  54.     longword    mask;
  55.     } gate_tables;
  56.  
  57. #define ARP_FLAG_NEED    0
  58. #define ARP_FLAG_FOUND  1
  59. #define ARP_FLAG_FIXED  255        /* cannot be removed */
  60. extern longword ipbcast;        /* IP broadcast address */
  61.  
  62. /*
  63.  * arp resolution cache - we zero fill it to save an initialization routine
  64.  */
  65.  
  66. static arp_tables arp_data[MAX_ARP_DATA];
  67. gate_tables arp_gate_data[MAX_GATE_DATA];
  68. word arp_last_gateway = 0;
  69. static word arp_index = 0;        /* rotates round-robin */
  70.  
  71. void
  72. arp_init()        /* init to zero ARP and arp_gateway tables */
  73. {
  74.     static first_time = 0;
  75.  
  76.     if (first_time == 0)
  77.         {
  78.         memset((byte *)arp_data, 0, sizeof(arp_tables) * MAX_ARP_DATA);
  79.         memset((byte *)arp_gate_data, 0, 
  80.                 sizeof(gate_tables) * MAX_GATE_DATA);
  81.         }
  82.     arp_last_gateway = 0;        /* reset the gateway table */
  83.     first_time = 1;            /* to keep arp_tables on hot start */
  84. }
  85.  
  86. /*
  87.  * arp_add_gateway - if data is NULL, don't use string
  88.  */
  89. void 
  90. arp_add_gateway(byte *data, longword ip)
  91. {
  92.     int i;
  93.     register byte *subnetp, *maskp;
  94.     longword subnet, mask;
  95.  
  96.     if ((data == NULL) && (ip == 0L)) return;     /* nothing to do */
  97.     subnet = mask = 0;
  98.     if (data != NULL)
  99.         {
  100.         maskp = NULL;
  101.         if ((subnetp = strchr(data, ',')) != NULL)
  102.             {
  103.             *subnetp++ = 0;
  104.             if (maskp = strchr(subnetp, ','))
  105.                 {
  106.                 *maskp++ = 0;
  107.                 mask = aton(maskp);
  108.                 subnet = aton(subnetp);
  109.                 }
  110.             else
  111.                 {
  112.                 subnet = aton(subnetp);
  113.                 switch (i = (subnet >> 30) & 0x000f)
  114.                     {
  115.                     case 0:
  116.                         case 1: mask = 0xff000000L; break;
  117.                     case 2: mask = 0xfffffe00L; break;
  118.                     case 3: mask = 0xffffff00L; break;
  119.                     }
  120.                 }
  121.             }
  122.             }
  123.  
  124.     if (arp_last_gateway >= MAX_GATE_DATA) return;
  125.  
  126.     for (i = 0; i < arp_last_gateway; i++)
  127.         if (arp_gate_data[i].mask < mask)
  128.             {
  129.             bcopy(&arp_gate_data[i], &arp_gate_data[i+1],
  130.                 (arp_last_gateway - i) * sizeof(gate_tables));
  131.             break;
  132.             }
  133.  
  134.     if ((data != NULL) && (ip == 0L))    /* if text form given */
  135.         ip = aton(data);        /* convert to 32 bit long */
  136.  
  137.     arp_gate_data[i].gate_ip = ip;
  138.     arp_gate_data[i].subnet = subnet;
  139.     arp_gate_data[i].mask = mask;
  140.     arp_last_gateway++;            /* used up another one */
  141. }
  142.  
  143. longword
  144. arp_rpt_gateway(int i)            /* report IP of gateway i */
  145. {
  146.     if (i >= 0 && i < MAX_GATE_DATA)
  147.         return (arp_gate_data[i].gate_ip);
  148.     else    return (0L);
  149. }
  150.  
  151. static void 
  152. arp_request(longword ip)
  153. {
  154.     register arp_Header *op;
  155.  
  156.     op = (arp_Header *)eth_formatpacket(ð_brdcast[0], 0x0608);
  157.     op->hwType = arp_TypeEther;
  158.     op->protType = 0x0008;                /* IP Ethertype*/
  159.     op->hwProtAddrLen = sizeof(eth_address) + (sizeof(longword) << 8);
  160.     op->opcode = ARP_REQUEST;
  161.     op->srcIPAddr = intel(my_ip_addr);
  162.     bcopy(eth_addr, op->srcEthAddr, sizeof(eth_address));
  163.     op->dstIPAddr = intel(ip);
  164.     eth_send(sizeof(arp_Header));            /* send the packet */
  165. }
  166.  
  167. static arp_tables *
  168. arp_search(longword ip, int create)
  169. {
  170.     register int i;
  171.     register arp_tables *arp_ptr;
  172.  
  173.     for (i = 0; i < MAX_ARP_DATA; i++)
  174.         if (ip == arp_data[i].ip)
  175.             return(&arp_data[i]);
  176.                         /* didn't find any */
  177.     if (create != 0)
  178.         {            /* pick an old or empty one */
  179.         for (i = 0; i < MAX_ARP_DATA; i++)
  180.             {
  181.             arp_ptr = &arp_data[i];
  182.             if ((arp_ptr->ip == 0L) ||
  183.                     chk_timeout(arp_ptr->expiry + MAX_ARP_GRACE))
  184.             return(arp_ptr);
  185.             }
  186.                     /* pick one at pseudo-random */
  187.         return (&arp_data[arp_index =
  188.                 (arp_index + 1) % MAX_ARP_DATA]);
  189.         }
  190.     return (NULL);
  191. }
  192.  
  193. void 
  194. arp_register(longword use, longword instead_of)
  195. {
  196.     register arp_tables *arp_ptr;
  197.  
  198.     if (arp_ptr = arp_search(instead_of, 0))
  199.         {    /* now insert the address of the new guy */
  200.         arp_ptr->flags = ARP_FLAG_NEED;
  201.         arp_resolve(use, arp_ptr->hardware);
  202.         arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  203.         return;
  204.         }
  205.     arp_ptr = arp_search(use, 1);    /* create a new one */
  206.     arp_ptr->flags = ARP_FLAG_NEED;
  207.     arp_ptr->ip = instead_of;
  208.     arp_resolve(use, arp_ptr->hardware);
  209.     arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  210. }
  211.  
  212. void
  213. arp_tick(longword ip)
  214. {
  215.     register arp_tables *arp_ptr;
  216.  
  217.     if (arp_ptr = arp_search(ip, 0))
  218.         arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  219. }
  220.  
  221. /*
  222.  * arp_handler - handle incomming ARP packets
  223.  */
  224. int
  225. arp_handler(arp_Header *in)
  226. {
  227.     register arp_Header *op;
  228.     longword his_ip;
  229.     register arp_tables *arp_ptr;
  230.     int i;
  231.  
  232.     if (in == NULL) return (0);            /* failure */
  233.  
  234.     if (in->hwType != arp_TypeEther ||    /* have Ethernet hardware */
  235.         in->protType != 0x0008)        /* and Internet software */
  236.         return(0);            /* 0 means no, fail */
  237.  
  238.     /* continuously accept data - but only for people we talk to */
  239.     his_ip = intel(in->srcIPAddr);
  240.  
  241.     if ((arp_ptr = arp_search(his_ip, 0)) != NULL)/* do not create entry */
  242.         {
  243.         arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  244.         bcopy(in->srcEthAddr, arp_ptr->hardware, sizeof(eth_address));
  245.         arp_ptr->flags = ARP_FLAG_FOUND;
  246.         }
  247.  
  248.             /* does someone else want our Ethernet address ? */
  249.     if (in->opcode == ARP_REQUEST &&        /* and be a resolution req */
  250.         in->dstIPAddr == intel(my_ip_addr))    /* for my address */
  251.         {
  252.         op = (arp_Header *)eth_formatpacket(in->srcEthAddr, 0x0608);
  253.         op->hwType = arp_TypeEther;
  254.         op->protType = 0x0008;            /* IP Ethertype */
  255.         op->hwProtAddrLen = sizeof(eth_address) +
  256.                         (sizeof(longword) << 8);
  257.         op->opcode = ARP_REPLY;
  258.         op->dstIPAddr = in->srcIPAddr;
  259.         op->srcIPAddr = in->dstIPAddr;
  260.         bcopy(eth_addr, op->srcEthAddr, sizeof(eth_address));
  261.         bcopy(in->srcEthAddr, op->dstEthAddr, sizeof(eth_address));
  262.         return (eth_send(sizeof(arp_Header)));
  263.         }
  264.     return (1);                    /* for success */
  265. }
  266.  
  267. /*
  268.  * arp_resolve - resolve IP address to hardware address
  269.  */
  270. int
  271. arp_resolve(longword ina, eth_address *ethap)
  272. {
  273.     register arp_tables *arp_ptr;
  274.     register int i;
  275.     int j;
  276.     longword timeout, resend;
  277.     static int recurse = 0;
  278.  
  279.     if (pktdevclass == PD_SLIP)
  280.     /* we are running slip or somthing which does not use addresses */
  281.         return(1);
  282.  
  283.     if (ina == my_ip_addr)
  284.             {
  285.         if (ethap != NULL)
  286.             bcopy(eth_addr, ethap, sizeof(eth_address));
  287.         recurse = 0;
  288.         return(1);                /* success */
  289.         }
  290.     if (ina == 0L || ina == 0xffffffffL || ina == ipbcast)
  291.         return (0);    /* cannot resolve IP of 0's or 0xff's*/
  292.  
  293.     if (recurse > 6) return (0);            /* fail */
  294.     recurse++;
  295.                 /* attempt to solve with ARP cache */
  296.     while (arp_ptr = arp_search(ina, 0))
  297.         {
  298.         if (strncmp(arp_ptr->hardware, eth_none, sizeof(eth_address)))
  299.             {
  300.                          /* has been resolved */
  301. #ifdef NEW_EXPIRY
  302.             if (chk_timeout(arp_ptr->expiry))
  303.                 {
  304.                 if (! chk_timeout(arp_ptr->expiry +
  305.                     MAX_ARP_GRACE))
  306.                     /* we wish to refresh it asynchronously */
  307.                     arp_request(ina);
  308.                 else
  309.                     break;    /* must do full fledged arp */
  310.                 }
  311. #endif /* NEW_EXPIRY */
  312.             if ((arp_ptr->flags == ARP_FLAG_FOUND) ||
  313.                 (arp_ptr->flags == ARP_FLAG_FIXED))
  314.                 {
  315.                         /* we found a valid hardware address */
  316.                 if (ethap != NULL)
  317.                         {
  318.                     bcopy(arp_ptr->hardware, ethap, 
  319.                         sizeof(eth_address));
  320.                     recurse = 0;
  321.                     return(1);        /* success */
  322.                     }
  323.                 }    /* end of if ((arp_ptr... */
  324.             }        /* end of if (strncmp... main */
  325.         else break;
  326.         }            /* end of while */
  327.  
  328.                         /* make a new one if necessary */
  329.     if (arp_ptr == NULL)
  330.             {
  331.         arp_ptr = arp_search(ina, 1);    /* 1 means create an entry */
  332.         arp_ptr->flags = ARP_FLAG_NEED;    /* say need a real entry */
  333.         }
  334.  
  335.         /* we must look elsewhere - but is it on our subnet? */
  336.     if ((ina ^ my_ip_addr) & sin_mask)    /* not of this network */
  337.         {
  338.         j = 0;                /* init status return */
  339.         for (i = 0; i < arp_last_gateway; i++)
  340.             {        /* compare the various subnet bits */
  341.                 if ((arp_gate_data[i].mask & ina) == 
  342.                 arp_gate_data[i].subnet)
  343.                     /* watch out RECURSIVE CALL! */
  344.                 if ((j = arp_resolve(arp_gate_data[i].gate_ip,
  345.                     ethap)) != 0)
  346.                         break;        /* success */
  347.             }
  348.         recurse--;
  349.         return (j);
  350.             }
  351.  
  352.     if (ina == 0L)        /* return if no host, or no gateway */
  353.             {
  354.         recurse--;
  355.         outs("\r\n Cannot find a gateway");
  356.         return(0);                    /* fail */
  357.         }
  358.  
  359.                     /* is on our subnet, we must resolve */
  360.     timeout = set_timeout(2);    /* two seconds is long for ARP */
  361.     while (!chk_timeout(timeout))
  362.         {    /* do the request */
  363.         arp_request(arp_ptr->ip = ina);
  364.         resend = set_timeout(1) - 14L;        /* 250 ms */
  365.         while (!chk_timeout(resend))
  366.             {
  367.             tcp_tick(NULL);            /* read packets */
  368.             if (arp_ptr->flags)
  369.                 {
  370.                 if (ethap != NULL)
  371.                     bcopy(arp_ptr->hardware, ethap, 
  372.                         sizeof(eth_address));
  373.                 arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  374.                 recurse = 0;
  375.                 return(1);            /* success */
  376.                 }
  377.             }
  378.             }
  379.     recurse--;
  380.     return(0);            /* fail */
  381. }
  382.  
  383.  
  384. int
  385. rarp_handler(arp_Header *in)
  386. {
  387.     register int i;
  388.     longword his_ip;
  389.     register arp_tables *arp_ptr;
  390.  
  391.     if (in == NULL) return (0);            /* failure */
  392.  
  393.             /* require Ethernet hardware and Internet software */
  394.     if ((in->hwType != arp_TypeEther) /* || (in->protType != 0x0008)*/)
  395.         return (0);                /* 0 means no, fail */
  396.  
  397.     his_ip = intel(in->srcIPAddr);
  398.     if ((arp_ptr = arp_search(his_ip, 0)) != NULL)
  399.         {
  400.         arp_ptr->expiry = set_timeout(MAX_ARP_ALIVE);
  401.         bcopy(in->srcEthAddr, arp_ptr->hardware, sizeof(eth_address));
  402.         arp_ptr->flags = ARP_FLAG_FOUND;
  403.         }
  404.  
  405.                     /* look for RARP Reply */
  406.     if ((my_ip_addr == 0) && (in->opcode == RARP_REPLY))
  407.         {              /* match our Ethernet address too */
  408.         for (i = 0; i < sizeof(eth_address); i++)
  409.             if (in->dstEthAddr[i] != eth_addr[i])
  410.                 return (1);        /* not for us */
  411.         my_ip_addr = intel(in->dstIPAddr);    /* our IP addr */
  412.         }
  413.     return (1);                    /* for success */
  414. }
  415.  
  416. /* send a RARP packet to request an IP address for our Ethernet address */
  417. static void 
  418. arp_rev_request(void)
  419. {
  420.     register arp_Header *op;
  421.  
  422.     op = (arp_Header *)eth_formatpacket(ð_brdcast[0], 0x3580); /*RARP */
  423.     op->hwType = arp_TypeEther;
  424.     op->protType = 0x0008;                /* IP Ethertype */
  425.     op->hwProtAddrLen = sizeof(eth_address) + (sizeof(longword) << 8);
  426.     op->opcode = RARP_REQUEST;
  427.     op->srcIPAddr = 0L;                /* we have no IP */
  428.     bcopy(eth_addr, op->srcEthAddr, sizeof(eth_address));
  429.     op->dstIPAddr = 0L;
  430.     bcopy(eth_addr, op->dstEthAddr, sizeof(eth_address));
  431.     eth_send(sizeof(arp_Header));            /* send the packet */
  432. }
  433.  
  434. /* Send a series of RARP requests until our IP address is non-zero or
  435.    we timeout.
  436. */
  437. int
  438. do_rarp(void)
  439. {
  440.     longword timeout, resend;
  441.  
  442.     timeout = set_timeout(10);            /* 10 seconds total */
  443.     while (chk_timeout(timeout) == 0)
  444.             {
  445.         arp_rev_request();            /* ask for our IP */
  446.         resend = set_timeout(1);        /* two second retry */
  447.         while (chk_timeout(resend) == 0)
  448.             {
  449.             tcp_tick(NULL);            /* read packets */
  450.             if (my_ip_addr != 0L) return (1); /* got a reply */
  451.             }
  452.         }
  453.     return (0);                    /* got no reply */
  454. }
  455.